import * as fs from 'fs';
import * as path from 'path';
import { Logger } from '../../src/logger/Logger';

/**
 * 增强的代码库索引器
 * 深度学习：测试子目录结构、完整的BUILD.gn配置、cpp内容、cpp与GN的关系
 */
export class EnhancedCodebaseIndexer {
    private ohCodePath: string;
    private enhancedKnowledge: any = {
        // 测试模块完整结构
        testModules: [],
        
        // BUILD.gn 深度模式
        buildGnFullPatterns: [],
        
        // CPP 测试代码模式
        cppTestPatterns: [],
        
        // CPP 与 GN 的关系
        cppGnRelations: [],
        
        // Sources 引用模式
        sourcesPatterns: {
            projectSource: [],     // ${xxx_path}/...
            localTest: [],         // 本地测试文件
            mockFiles: []          // Mock 文件
        },
        
        // Include_dirs 模式
        includeDirsPatterns: [],
        
        // Deps 模式
        depsPatterns: {
            internal: [],          // ${xxx_path}:xxx
            external: []           // "component:module"
        },
        
        // Defines 模式
        definesPatterns: [],
        
        // Module_out_path 命名规则
        moduleOutPathPatterns: []
    };

    constructor(ohCodePath: string) {
        this.ohCodePath = ohCodePath;
    }

    /**
     * 执行增强学习
     */
    public async enhancedLearn(): Promise<void> {
        Logger.info('\n🎓 增强代码库学习系统 - 深度分析');
        Logger.info('====================================\n');
        
        const projects = this.discoverProjects();
        Logger.info(`[EnhancedIndexer] 发现 ${projects.length} 个 OH 工程`);
        Logger.info(`[EnhancedIndexer] 将深度学习每个工程的测试结构\n`);

        for (const project of projects) {
            await this.learnProjectDeep(project);
        }

        // 统计和总结
        this.summarizePatterns();

        Logger.info('\n✅ 增强学习完成！\n');
    }

    /**
     * 发现工程
     */
    private discoverProjects(): any[] {
        const projects: any[] = [];
        
        try {
            const entries = fs.readdirSync(this.ohCodePath, { withFileTypes: true });
            
            for (const entry of entries) {
                if (entry.isDirectory()) {
                    const projectPath = path.join(this.ohCodePath, entry.name);
                    const bundleJsonPath = path.join(projectPath, 'bundle.json');
                    
                    if (fs.existsSync(bundleJsonPath)) {
                        projects.push({
                            name: entry.name,
                            path: projectPath
                        });
                    }
                }
            }
        } catch (error) {
            Logger.error(`发现工程失败: ${error}`);
        }
        
        return projects;
    }

    /**
     * 深度学习单个工程
     */
    private async learnProjectDeep(project: any): Promise<void> {
        Logger.info(`[EnhancedIndexer] 📚 学习工程: ${project.name}`);

        // 1. 学习 unittest 结构
        await this.learnUnittestStructure(project);

        // 2. 学习 fuzztest 结构
        await this.learnFuzztestStructure(project);
    }

    /**
     * 学习 unittest 结构
     */
    private async learnUnittestStructure(project: any): Promise<void> {
        const unittestDirs = [
            path.join(project.path, 'test', 'unittest'),
            path.join(project.path, 'test', 'unittests')
        ];

        for (const unittestDir of unittestDirs) {
            if (!fs.existsSync(unittestDir)) continue;

            // 获取所有测试子目录（每个子目录是一个测试模块）
            const testModuleDirs = fs.readdirSync(unittestDir, { withFileTypes: true })
                .filter(d => d.isDirectory() && d.name !== 'resource')
                .map(d => path.join(unittestDir, d.name));

            Logger.info(`[EnhancedIndexer]   - 发现 ${testModuleDirs.length} 个 unittest 模块`);

            for (const moduleDir of testModuleDirs) {
                await this.learnTestModule(project, moduleDir, 'unittest');
            }
        }
    }

    /**
     * 学习测试模块（核心）
     */
    private async learnTestModule(project: any, moduleDir: string, testType: string): Promise<void> {
        const moduleName = path.basename(moduleDir);
        
        try {
            const moduleInfo: any = {
                projectName: project.name,
                moduleName,
                testType,
                structure: {
                    files: [],
                    testFiles: [],
                    mockFiles: [],
                    hasBuildGn: false
                },
                buildGn: null,
                cppTests: [],
                cppGnRelations: []
            };

            // 1. 扫描模块文件
            const files = fs.readdirSync(moduleDir);
            moduleInfo.structure.files = files;
            moduleInfo.structure.testFiles = files.filter(f => 
                f.endsWith('_test.cpp') || f.endsWith('_test.cc')
            );
            moduleInfo.structure.mockFiles = files.filter(f => 
                f.toLowerCase().includes('mock')
            );

            // 2. 学习 BUILD.gn（完整配置）
            const buildGnPath = path.join(moduleDir, 'BUILD.gn');
            if (fs.existsSync(buildGnPath)) {
                moduleInfo.structure.hasBuildGn = true;
                const buildGnContent = fs.readFileSync(buildGnPath, 'utf-8');
                moduleInfo.buildGn = this.parseBuildGnComplete(buildGnContent, project.name, moduleName);
                
                // 提取 BUILD.gn 模式
                this.extractBuildGnPatterns(moduleInfo.buildGn);
            }

            // 3. 学习 CPP 测试文件内容
            for (const testFile of moduleInfo.structure.testFiles) {
                const testFilePath = path.join(moduleDir, testFile);
                try {
                    const cppContent = fs.readFileSync(testFilePath, 'utf-8');
                    const cppPattern = this.parseCppTest(cppContent, testFile, project.name);
                    moduleInfo.cppTests.push(cppPattern);
                    
                    // 提取 CPP 模式
                    this.enhancedKnowledge.cppTestPatterns.push(cppPattern);
                } catch (error) {
                    // 忽略读取错误
                }
            }

            // 4. 分析 CPP 与 GN 的关系
            if (moduleInfo.buildGn && moduleInfo.cppTests.length > 0) {
                const relation = this.analyzeCppGnRelation(moduleInfo);
                moduleInfo.cppGnRelations.push(relation);
                this.enhancedKnowledge.cppGnRelations.push(relation);
            }

            this.enhancedKnowledge.testModules.push(moduleInfo);

        } catch (error) {
            Logger.warn(`  ⚠️  学习模块失败 ${moduleName}: ${error}`);
        }
    }

    /**
     * 完整解析 BUILD.gn
     */
    private parseBuildGnComplete(content: string, projectName: string, moduleName: string): any {
        const parsed: any = {
            projectName,
            moduleName,
            rawContent: content.substring(0, 500), // 保存部分原始内容
            imports: [],
            variables: {},
            unittestTargets: [],
            groupTarget: null
        };

        // 1. 提取 import 语句
        const importMatches = content.matchAll(/import\("([^"]+)"\)/g);
        for (const match of importMatches) {
            parsed.imports.push(match[1]);
        }

        // 2. 提取变量定义
        const variableMatches = content.matchAll(/(\w+)\s*=\s*"([^"]+)"/g);
        for (const match of variableMatches) {
            parsed.variables[match[1]] = match[2];
        }

        // 3. 完整解析 ohos_unittest 块
        const unittestRegex = /ohos_unittest\("([^"]+)"\)\s*\{([\s\S]*?)(?:^|\n)\}/gm;
        const unittestMatches = content.matchAll(unittestRegex);

        for (const match of unittestMatches) {
            const targetName = match[1];
            const targetContent = match[2];
            
            const target: any = {
                name: targetName,
                moduleOutPath: this.extractStringField(targetContent, 'module_out_path'),
                sources: this.extractArrayField(targetContent, 'sources'),
                includeDirs: this.extractArrayField(targetContent, 'include_dirs'),
                deps: this.extractArrayField(targetContent, 'deps'),
                externalDeps: this.extractArrayField(targetContent, 'external_deps'),
                defines: this.extractArrayField(targetContent, 'defines'),
                cflags: this.extractArrayField(targetContent, 'cflags'),
                ldflags: this.extractArrayField(targetContent, 'ldflags'),
                
                // 额外字段
                branchProtectorRet: this.extractStringField(targetContent, 'branch_protector_ret'),
                useExceptions: targetContent.includes('use_exceptions = true'),
                sanitize: this.extractSanitize(targetContent)
            };

            parsed.unittestTargets.push(target);
        }

        // 4. 提取 group 目标
        const groupMatch = content.match(/group\("([^"]+)"\)\s*\{([^}]+)\}/s);
        if (groupMatch) {
            parsed.groupTarget = {
                name: groupMatch[1],
                deps: this.extractArrayField(groupMatch[2], 'deps'),
                testonly: groupMatch[2].includes('testonly = true')
            };
        }

        return parsed;
    }

    /**
     * 提取字符串字段
     */
    private extractStringField(content: string, fieldName: string): string | null {
        const regex = new RegExp(`${fieldName}\\s*=\\s*"([^"]+)"`, 'i');
        const match = content.match(regex);
        return match ? match[1] : null;
    }

    /**
     * 提取数组字段
     */
    private extractArrayField(content: string, fieldName: string): string[] {
        const regex = new RegExp(`${fieldName}\\s*=\\s*\\[([^\\]]+(?:\\[[^\\]]*\\][^\\]]*)*?)\\]`, 'is');
        const match = content.match(regex);
        
        if (!match) return [];
        
        const arrayContent = match[1];
        const items: string[] = [];
        
        // 提取引号内的内容
        const itemRegex = /"([^"]+)"/g;
        let itemMatch;
        
        while ((itemMatch = itemRegex.exec(arrayContent)) !== null) {
            items.push(itemMatch[1]);
        }
        
        return items;
    }

    /**
     * 提取 sanitize 配置
     */
    private extractSanitize(content: string): any {
        const sanitizeMatch = content.match(/sanitize\s*=\s*\{([^}]+)\}/s);
        if (!sanitizeMatch) return null;
        
        const sanitizeContent = sanitizeMatch[1];
        return {
            integerOverflow: sanitizeContent.includes('integer_overflow = true'),
            cfi: sanitizeContent.includes('cfi = true'),
            cfiCrossDso: sanitizeContent.includes('cfi_cross_dso = true'),
            debug: sanitizeContent.includes('debug = true')
        };
    }

    /**
     * 解析 CPP 测试文件
     */
    private parseCppTest(content: string, fileName: string, projectName: string): any {
        return {
            projectName,
            fileName,
            
            // 基本信息
            hasGTest: content.includes('gtest/gtest.h'),
            hasGMock: content.includes('gmock/gmock.h'),
            usesHWTEST_F: content.includes('HWTEST_F'),
            
            // 头文件
            includes: this.extractIncludes(content),
            
            // 命名空间
            namespaces: this.extractNamespaces(content),
            
            // 测试类
            testClasses: this.extractTestClasses(content),
            
            // 测试用例数量
            testCaseCount: (content.match(/HWTEST_F/g) || []).length,
            
            // Mock 使用
            mockUsage: {
                hasMockFunction: content.includes('MOCK_METHOD'),
                hasExpectCall: content.includes('EXPECT_CALL'),
                hasNiceMock: content.includes('NiceMock')
            },
            
            // 代码片段（前500字符）
            snippet: content.substring(0, 500)
        };
    }

    /**
     * 提取 include 语句
     */
    private extractIncludes(content: string): string[] {
        const includes: string[] = [];
        const includeRegex = /#include\s+[<"]([^>"]+)[>"]/g;
        let match;
        
        while ((match = includeRegex.exec(content)) !== null) {
            includes.push(match[1]);
        }
        
        return includes;
    }

    /**
     * 提取命名空间
     */
    private extractNamespaces(content: string): string[] {
        const namespaces: string[] = [];
        const namespaceRegex = /namespace\s+(\w+)/g;
        let match;
        
        while ((match = namespaceRegex.exec(content)) !== null) {
            namespaces.push(match[1]);
        }
        
        return [...new Set(namespaces)];
    }

    /**
     * 提取测试类
     */
    private extractTestClasses(content: string): string[] {
        const classes: string[] = [];
        const classRegex = /class\s+(\w+)\s*:\s*public/g;
        let match;
        
        while ((match = classRegex.exec(content)) !== null) {
            classes.push(match[1]);
        }
        
        return classes;
    }

    /**
     * 分析 CPP 与 GN 的关系
     */
    private analyzeCppGnRelation(moduleInfo: any): any {
        const relation: any = {
            projectName: moduleInfo.projectName,
            moduleName: moduleInfo.moduleName,
            cppIncludes: [],
            gnIncludeDirs: [],
            matchRate: 0,
            cppDependencies: [],
            gnExternalDeps: [],
            recommendations: []
        };

        // 从所有 CPP 文件收集 includes
        for (const cpp of moduleInfo.cppTests) {
            relation.cppIncludes.push(...cpp.includes);
        }
        relation.cppIncludes = [...new Set(relation.cppIncludes)];

        // 从 GN 获取 include_dirs
        if (moduleInfo.buildGn && moduleInfo.buildGn.unittestTargets.length > 0) {
            const target = moduleInfo.buildGn.unittestTargets[0];
            relation.gnIncludeDirs = target.includeDirs || [];
            relation.gnExternalDeps = target.externalDeps || [];
        }

        // 分析匹配率和给出建议
        // （简化版，实际可以更复杂）
        if (relation.cppIncludes.length > 0) {
            // 检查常见依赖是否在 GN 中
            const needHilog = relation.cppIncludes.some((inc: string) => inc.includes('hilog'));
            const hasHilog = relation.gnExternalDeps.some((dep: string) => dep.includes('hilog'));
            
            if (needHilog && !hasHilog) {
                relation.recommendations.push('添加 hilog:libhilog 到 external_deps');
            }
        }

        return relation;
    }

    /**
     * 提取 BUILD.gn 模式
     */
    private extractBuildGnPatterns(buildGn: any): void {
        for (const target of buildGn.unittestTargets || []) {
            // 完整的 BUILD.gn 模式
            this.enhancedKnowledge.buildGnFullPatterns.push({
                projectName: buildGn.projectName,
                moduleName: buildGn.moduleName,
                targetName: target.name,
                moduleOutPath: target.moduleOutPath,
                
                // Sources 分类
                sourcesInfo: this.classifySources(target.sources),
                
                // Include_dirs
                includeDirs: target.includeDirs || [],
                
                // Dependencies
                internalDeps: target.deps || [],
                externalDeps: target.externalDeps || [],
                
                // Defines
                defines: target.defines || [],
                
                // 其他
                useExceptions: target.useExceptions,
                sanitize: target.sanitize
            });

            // Sources 模式
            this.extractSourcesPatterns(target.sources, buildGn.projectName);

            // Include_dirs 模式
            this.extractIncludeDirsPatterns(target.includeDirs, buildGn.projectName);

            // Deps 模式
            this.extractDepsPatterns(target.deps, target.externalDeps, buildGn.projectName);

            // Defines 模式
            this.extractDefinesPatterns(target.defines, buildGn.projectName);

            // Module_out_path 模式
            if (target.moduleOutPath) {
                this.enhancedKnowledge.moduleOutPathPatterns.push({
                    projectName: buildGn.projectName,
                    pattern: target.moduleOutPath
                });
            }
        }
    }

    /**
     * 分类 sources
     */
    private classifySources(sources: string[]): any {
        if (!sources) return { projectSources: [], testFiles: [], mockFiles: [], total: 0 };
        
        return {
            projectSources: sources.filter(s => s.includes('${') || s.includes('../')),
            testFiles: sources.filter(s => s.endsWith('_test.cpp') || s.endsWith('_test.cc')),
            mockFiles: sources.filter(s => s.toLowerCase().includes('mock')),
            total: sources.length
        };
    }

    /**
     * 提取 sources 模式
     */
    private extractSourcesPatterns(sources: string[], projectName: string): void {
        if (!sources) return;
        
        for (const source of sources) {
            if (source.includes('${')) {
                this.enhancedKnowledge.sourcesPatterns.projectSource.push({
                    projectName,
                    pattern: source,
                    variable: source.match(/\$\{([^}]+)\}/)?.[1]
                });
            } else if (source.endsWith('_test.cpp') || source.endsWith('_test.cc')) {
                this.enhancedKnowledge.sourcesPatterns.localTest.push({
                    projectName,
                    file: source
                });
            } else if (source.toLowerCase().includes('mock')) {
                this.enhancedKnowledge.sourcesPatterns.mockFiles.push({
                    projectName,
                    file: source
                });
            }
        }
    }

    /**
     * 提取 include_dirs 模式
     */
    private extractIncludeDirsPatterns(includeDirs: string[], projectName: string): void {
        if (!includeDirs) return;
        
        for (const dir of includeDirs) {
            this.enhancedKnowledge.includeDirsPatterns.push({
                projectName,
                pattern: dir,
                hasVariable: dir.includes('${'),
                isAbsolute: dir.startsWith('/')
            });
        }
    }

    /**
     * 提取 deps 模式
     */
    private extractDepsPatterns(deps: string[], externalDeps: string[], projectName: string): void {
        if (deps) {
            for (const dep of deps) {
                this.enhancedKnowledge.depsPatterns.internal.push({
                    projectName,
                    dependency: dep
                });
            }
        }
        
        if (externalDeps) {
            for (const dep of externalDeps) {
                this.enhancedKnowledge.depsPatterns.external.push({
                    projectName,
                    dependency: dep
                });
            }
        }
    }

    /**
     * 提取 defines 模式
     */
    private extractDefinesPatterns(defines: string[], projectName: string): void {
        if (!defines) return;
        
        for (const define of defines) {
            this.enhancedKnowledge.definesPatterns.push({
                projectName,
                define
            });
        }
    }

    /**
     * 学习 fuzztest 结构
     */
    private async learnFuzztestStructure(project: any): Promise<void> {
        const fuzztestDir = path.join(project.path, 'test', 'fuzztest');
        
        if (!fs.existsSync(fuzztestDir)) return;

        const fuzzerDirs = fs.readdirSync(fuzztestDir, { withFileTypes: true })
            .filter(d => d.isDirectory() && d.name.endsWith('_fuzzer'))
            .map(d => path.join(fuzztestDir, d.name));

        if (fuzzerDirs.length > 0) {
            Logger.info(`[EnhancedIndexer]   - 发现 ${fuzzerDirs.length} 个 fuzztest 模块`);
        }

        for (const fuzzerDir of fuzzerDirs) {
            await this.learnTestModule(project, fuzzerDir, 'fuzztest');
        }
    }

    /**
     * 总结模式
     */
    private summarizePatterns(): void {
        Logger.info('\n📊 学习统计：');
        Logger.info(`  ✓ 测试模块: ${this.enhancedKnowledge.testModules.length}`);
        Logger.info(`  ✓ BUILD.gn完整模式: ${this.enhancedKnowledge.buildGnFullPatterns.length}`);
        Logger.info(`  ✓ CPP测试模式: ${this.enhancedKnowledge.cppTestPatterns.length}`);
        Logger.info(`  ✓ CPP-GN关系: ${this.enhancedKnowledge.cppGnRelations.length}`);
        Logger.info(`  ✓ Sources模式: ${
            this.enhancedKnowledge.sourcesPatterns.projectSource.length + 
            this.enhancedKnowledge.sourcesPatterns.localTest.length +
            this.enhancedKnowledge.sourcesPatterns.mockFiles.length
        }`);
        Logger.info(`  ✓ Include_dirs模式: ${this.enhancedKnowledge.includeDirsPatterns.length}`);
        Logger.info(`  ✓ Deps模式: ${
            this.enhancedKnowledge.depsPatterns.internal.length + 
            this.enhancedKnowledge.depsPatterns.external.length
        }`);
    }

    /**
     * 保存增强知识
     */
    public async save(savePath: string): Promise<void> {
        const data = {
            ...this.enhancedKnowledge,
            learnedAt: new Date().toISOString(),
            projectCount: this.discoverProjects().length,
            version: '2.0-enhanced'
        };

        fs.writeFileSync(savePath, JSON.stringify(data, null, 2), 'utf-8');
        Logger.info(`\n💾 增强知识已保存: ${savePath}`);
        
        // 显示文件大小
        const stats = fs.statSync(savePath);
        const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
        Logger.info(`📊 知识库大小: ${sizeMB} MB`);
    }

    /**
     * 获取增强知识
     */
    public getEnhancedKnowledge(): any {
        return this.enhancedKnowledge;
    }
}

